#include <atomic>
#include <iostream>
#include <cassert>
#include <thread>
#include <vector>

template<typename T>
class SharedPtr{
private:
    T* ptr_;
    std::atomic<int>* count_;

    void release(){
        if(count_ && count_->fetch_sub(1) == 1){
            delete ptr_;
            delete count_;
        }
    }
public:
    // 构造，析构，拷贝，移动
    explicit SharedPtr(T* ptr = nullptr) : ptr_(ptr), count_(new std::atomic<int>(ptr ? 1: 0)) {}
    ~SharedPtr() { release(); }

    SharedPtr(const SharedPtr& other) noexcept
        : ptr_(other.ptr_), count_(other.count_) {
        if(count_) ++(*count_);
    }

    SharedPtr& operator=(const SharedPtr& other) noexcept {
        if(this == &other) return *this;
        release();
        ptr_ = other.ptr_;
        count_ = other.count_;
        if (count_) ++(*count_);
        return *this;
    }

    SharedPtr(SharedPtr&& other) noexcept
        : ptr_(other.ptr_), count_(other.count_) {
            other.ptr_ = nullptr;
            other.count_ = nullptr;
    }

    SharedPtr& operator=(SharedPtr&& other) noexcept {
        if(this == &other) return *this;
        release();
        ptr_ = other.ptr_;
        count_ = other.count_;
        other.ptr_ = nullptr;
        other.count_ = nullptr;
        return *this;
    }

    // 访问接口
    T& operator*() const {
        assert(ptr_);
        return *ptr_;
    }

    T* operator->() const {
        assert(ptr_);
        return ptr_;
    }

    T* get() const noexcept { return ptr_; }

    explicit operator bool() const noexcept { return ptr_ != nullptr; }

    int use_count() const noexcept { return count_ ? count_->load() : 0; }
    
    // 控制接口
    void reset(T* new_ptr = nullptr) {
        release();
        ptr_ = new_ptr;
        count_ = new std::atomic<int>(new_ptr ? 1 : 0);
    }
};

/* ---------- 测试代码 ---------- */
int main() {
    SharedPtr<int> p1(new int(42));
    {
        SharedPtr<int> p2 = p1; // 拷贝，引用计数=2
        std::cout << p2.use_count() << "\n"; // 输出 2
    } // p2 析构，引用计数=1
    std::cout << p1.use_count() << "\n"; // 输出 1
} // p1 析构，引用计数=0，释放内存